package xyz.bali16.module.rank.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.gitee.starblues.bootstrap.annotation.AutowiredType;
import com.gitee.starblues.spring.MainApplicationContext;
import com.gitee.starblues.spring.SpringBeanFactory;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import xyz.bali16.application.core.model.Result;
import xyz.bali16.application.core.model.UserVo;
import xyz.bali16.application.core.utils.PageUtils;
import xyz.bali16.application.core.utils.RedisUtil;
import xyz.bali16.application.entity.User;
import xyz.bali16.application.service.UserService;
import xyz.bali16.module.activeuser.entity.ActiveUser;
import xyz.bali16.module.activeuser.model.ActiveUserPageParam;
import xyz.bali16.module.activeuser.service.ActiveUserService;
import xyz.bali16.module.article.entity.Article;
import xyz.bali16.module.article.service.ArticleService;
import xyz.bali16.module.rank.service.ActiveUserServiceCaller;
import xyz.bali16.module.rank.service.ArticleRankServiceCaller;


import java.util.*;

import static xyz.bali16.application.core.model.Result.*;
import static xyz.bali16.application.core.model.Result.failure;

/**
 * @author bali2 on 9/3/2023.
 * @version 1.0
 */
@RestController
@RequestMapping(BaseController.API + "rank")
@Api(tags = "排行榜接口")
@AllArgsConstructor

public class RankController extends BaseController {
    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    private MainApplicationContext context;
    @Autowired
    ActiveUserServiceCaller activeUserServiceCaller;
    @Autowired
    ArticleRankServiceCaller articleRankServiceCaller;
    @ApiOperation("获取排行板块")
    @GetMapping("/getRank")
    public Result<PageUtils> getRank(String by, String type) {
        Integer currPage = 0;
        Integer pageSize = 10;
        // 帖子:article/post
        if (by.equals("article")) {
            return handleArticlesWeekRank(type, currPage, pageSize);
        }
        if (by.equals("blog")) {

        }
        if (by.equals("user")) {
            PageUtils pageUtils = new PageUtils(currPage, pageSize, activeUserServiceCaller.getRank(currPage, pageSize));
            return success(pageUtils);
        }
        return null;
    }

    public Result<PageUtils> handleArticlesWeekRank(String type, Integer currPage, Integer pageSize) {
        String weekRankKey = "week:rank:" + type;
        Set<String> weekRankArticles = redisTemplate.opsForZSet().reverseRange(weekRankKey, currPage, pageSize);
        List<Map> hotPosts = new ArrayList<>();
        for (String articleId : weekRankArticles) {
            Map<String, Object> map = new HashMap<>();

            String postKey = "rank:article:" + articleId;
            map.put("id", articleId);
            map.put("title", redisTemplate.opsForHash().get(postKey, "article:title"));
            // 根据类型进行返回数值
            switch (type) {
                case "commentCount":
                    map.put("commentCount", redisTemplate.opsForZSet().score(weekRankKey, articleId));
                    break;
                case "like":
                    map.put("like", redisTemplate.opsForZSet().score(weekRankKey, articleId));
                    break;
                case "views":
                    map.put("views", redisTemplate.opsForZSet().score(weekRankKey, articleId));
                    break;
                case "collection":
                    map.put("collection", redisTemplate.opsForZSet().score(weekRankKey, articleId));
                    break;

            }
            Article article = articleRankServiceCaller.supperGetById(articleId);
            map.put("article",article);
            hotPosts.add(map);
        }
        PageUtils pageUtils = new PageUtils(currPage, pageSize, hotPosts);
        return success(pageUtils);
    }

    @GetMapping("/commentArticlesWeekRank")
    public Result<PageUtils> commentArticlesWeekRank(@RequestParam Integer currPage, @RequestParam Integer pageSize) {
        String weekRankKey = "week:rank:commentCount";
        Set<String> weekRankArticles = redisTemplate.opsForZSet().reverseRange(weekRankKey, currPage, pageSize);
        List<Map> hotPosts = new ArrayList<>();

        for (String articleId : weekRankArticles) {

            Map<String, Object> map = new HashMap<>();

            String postKey = "rank:article:" + articleId;
            map.put("id", articleId);
            map.put("title", redisTemplate.opsForHash().get(postKey, "article:title"));
            map.put("commentCount", redisTemplate.opsForZSet().score(weekRankKey, articleId));
            hotPosts.add(map);
        }
        PageUtils pageUtils = new PageUtils(currPage, pageSize, hotPosts);
        return success(pageUtils);
    }

    @GetMapping("/likeArticlesWeekRank")
    public Result<PageUtils> likeArticlesWeekRank(@RequestParam Integer currPage, @RequestParam Integer pageSize) {
        String weekRankKey = "week:rank:like";
        Set<String> weekRankArticles = redisTemplate.opsForZSet().reverseRange(weekRankKey, currPage, pageSize);
        List<Map> hotPosts = new ArrayList<>();

        for (String articleId : weekRankArticles) {

            Map<String, Object> map = new HashMap<>();

            String postKey = "rank:article:" + articleId;
            map.put("id", articleId);
            map.put("title", redisTemplate.opsForHash().get(postKey, "article:title"));
            map.put("likeCount", redisTemplate.opsForZSet().score(weekRankKey, articleId));
            hotPosts.add(map);
        }
        PageUtils pageUtils = new PageUtils(currPage, pageSize, hotPosts);
        return success(pageUtils);
    }

    @GetMapping("/viewsArticlesWeekRank")
    public Result<PageUtils> viewsArticlesWeekRank(@RequestParam Integer currPage, @RequestParam Integer pageSize) {
        String weekRankKey = "week:rank:views";
        Set<String> weekRankArticles = redisTemplate.opsForZSet().reverseRange(weekRankKey, currPage, pageSize);
        List<Map> hotPosts = new ArrayList<>();

        for (String articleId : weekRankArticles) {

            Map<String, Object> map = new HashMap<>();

            String postKey = "rank:article:" + articleId;
            map.put("id", articleId);
            map.put("title", redisTemplate.opsForHash().get(postKey, "article:title"));
            map.put("viewsCount", redisTemplate.opsForZSet().score(weekRankKey, articleId));
            hotPosts.add(map);
        }
        PageUtils pageUtils = new PageUtils(currPage, pageSize, hotPosts);
        return success(pageUtils);
    }

    @GetMapping("/collectionArticlesWeekRank")
    public Result<PageUtils> collectionArticlesWeekRank(@RequestParam Integer currPage, @RequestParam Integer pageSize) {
        String weekRankKey = "week:rank:collection";
        Set<String> weekRankArticles = redisTemplate.opsForZSet().reverseRange(weekRankKey, currPage, pageSize);
        List<Map> hotPosts = new ArrayList<>();

        for (String articleId : weekRankArticles) {

            Map<String, Object> map = new HashMap<>();

            String postKey = "rank:article:" + articleId;
            map.put("id", articleId);
            map.put("title", redisTemplate.opsForHash().get(postKey, "article:title"));
            map.put("collectionCount", redisTemplate.opsForZSet().score(weekRankKey, articleId));
            hotPosts.add(map);
        }
        PageUtils pageUtils = new PageUtils(currPage, pageSize, hotPosts);
        return success(pageUtils);
    }
}
